package com.biubiushop.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.XMLOutputter;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * JSON转XML工具类
 * Created by chenjia on 2019-06-04
 *
 */
public class JsonUtil {

	/**
	 * xml转json
	 * @param xml
	 * @return JSON字符串
	 */
	public static String xmlToJSON(String xml) {
		JSONObject obj;
		try {
			InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
			SAXBuilder sb = new SAXBuilder();
			Document doc = sb.build(is);
			Element root = doc.getRootElement();
			Map<String, Object> map = iterateElement(root);
			obj = JSONObject.parseObject(JSONObject.toJSONString(map));
			return obj.toString();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static Map<String, Object> iterateElement(Element root) {
		List childrenList = root.getChildren();
		Element element = null;
		HashMap<String, Object> map = new LinkedHashMap<String, Object>();
		List list = null;
		for (int i = 0; i < childrenList.size(); i++) {
			list = new ArrayList();
			element = (Element) childrenList.get(i);
			if (element.getChildren().size() > 0) {
				if (root.getChildren(element.getName()).size() > 1) {
					if (map.containsKey(element.getName())) {
						list = (List) map.get(element.getName());
					}
					list.add(iterateElement(element));
					map.put(element.getName(), list);
				} else {
					map.put(element.getName(), iterateElement(element));
				}
			} else {
				if (root.getChildren(element.getName()).size() > 1) {
					if (map.containsKey(element.getName())) {
						list = (List) map.get(element.getName());
					}
					list.add(element.getTextTrim());
					map.put(element.getName(), list);
				} else {
					map.put(element.getName(), element.getTextTrim());
				}
			}
		}

		return map;
	}

	/**
	 * json字符串转xml
	 * @param json:json数据字符串
	 * @param includeXml:是否包含xml标签
	 * @return
	 */
	public static String jsonToXml(String json,Boolean includeXml) {
		if (json == null || json.isEmpty()) {
			return null;
		} else {
			JSONObject obj = JSONObject.parseObject(json,Feature.OrderedField);
			if(includeXml) {
				obj = obj.getJSONObject("xml");
			}
			Element elements = new Element("xml");
			getXMLFromObject(obj, "xml", elements);
			XMLOutputter xmlOut = new XMLOutputter();
			String res = xmlOut.outputString(elements);
			return res;
		}
	}

	private static void getXMLFromObject(Object obj, String tag, Element parent) {
		if (obj == null) {
			return;
		}
		Element child;
		Object childValue;
		if (obj instanceof JSONObject) {
			JSONObject jsonObject = (JSONObject) obj;
			for (String temp : jsonObject.keySet()) {
				childValue = jsonObject.get(temp);
				child = new Element(temp);
				if (childValue instanceof JSONArray) {
					getXMLFromObject(childValue, temp, parent);
				} else {
					parent.addContent(child);
					getXMLFromObject(childValue, temp, child);
				}
			}
		} else if (obj instanceof JSONArray) {
			JSONArray jsonArray = (JSONArray) obj;
			for (int i = 0; i < jsonArray.size(); i++) {
				childValue = jsonArray.get(i);
				child = new Element(tag);
				parent.addContent(child);
				getXMLFromObject(childValue, tag, child);
			}
		} else if (obj instanceof Date) {
			SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			parent.setText(sf.format((Date) obj));
		} else {
 			parent.setText(obj.toString());
		}
	}

	public static void main(String[] args) throws Exception {

		String xml = "<xml>\r\n" + "   <appid>wx2421b1c4370ec43b</appid>\r\n" + "<sign>0CB01533B8C1EF103065174F50BCA001</sign>\r\n"
				+ "</xml>";
		String json = xmlToJSON(xml);
		System.out.println(json);
		System.out.println("=====================================================");
//		String xmlStr = jsonToXml(json,true);
//		System.out.println(xmlStr);
//		System.out.println("=====================================================");
//		System.out.println(xmlToJSON(xmlStr));

	}
}
